package com.ditri.distrident.common.utils;

import com.ditri.distrident.common.constant.CommonConst;
import com.ditri.distrident.common.constant.ErrorCodeEnum;
import com.ditri.distrident.common.entity.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.data.redis.core.RedisTemplate;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * 发送短信
 *
 * @author: edxuanlen
 * @date: 2020-08-06 10:03
 * @version: 1.0
 **/

@Slf4j
public class SendSmsUtil {

    @Resource
    private static RedisTemplate<String, String> redisTemplate;

    public static Result sendSms(String phone) {

        // 限制一个小时内同一个账号发送短信验证码不能超过5条

        // 验证码key值
        String redisKey = CommonConst.Redis.AUTH_CODE_SEND_TIME_PREFIX + phone;
        // 查对应的记录
        String numberOfSendingWithOneHour = redisTemplate.opsForValue().get(redisKey);
        int numberOfSendingWithOneHourInt = 0;
        // 有记录
        if (!CommonUtil.isEmpty(numberOfSendingWithOneHour)) {
            assert numberOfSendingWithOneHour != null;
            numberOfSendingWithOneHourInt = Integer.parseInt(numberOfSendingWithOneHour);

            // 如果已经发送上限了，返回错误
            if (numberOfSendingWithOneHourInt >= CommonConst.Phone.MAX_NUMBER_OF_SENDING_WITH_ONE_HOUR) {
                return ErrorCodeEnum.SMS_SEND_FREQUENTLY.getResult();
            }
        }


        HttpClient client = new HttpClient();
        PostMethod method = new PostMethod(CommonConst.Phone.URL);

        client.getParams().setContentCharset("GBK");
        method.setRequestHeader("ContentType", "application/x-www-form-urlencoded;charset=GBK");

        int authCode = (int) ((Math.random() * 9 + 1) * 100000);

        String content = CommonConst.Phone.CONTENT_PREFIX + authCode + CommonConst.Phone.CONTENT_SUFFIX;

        NameValuePair[] data = {
                new NameValuePair("account", CommonConst.Phone.API_ID),
                new NameValuePair("password", CommonConst.Phone.API_KEY),
                new NameValuePair("mobile", phone),
                new NameValuePair("content", content),
        };

        method.setRequestBody(data);

        try {
            // 准备发送短信
            client.executeMethod(method);
            String submitResult = method.getResponseBodyAsString();
            Document doc = DocumentHelper.parseText(submitResult);
            Element root = doc.getRootElement();
            String code = root.elementText("code");
            String msg = root.elementText("msg");

            log.info(code);
            log.info(msg);

            switch (code) {
                // 发送成功
                case CommonConst.Phone.SMS_SEND_SUCCESSFUL:
                    // 发送成功后在redis记下验证码，两分钟失效
                    redisTemplate.opsForValue().set(CommonConst.Redis.AUTH_CODE_PREFIX + phone, String.valueOf(authCode), CommonConst.Time.SECONDS_OF_ONE_MIN * 2, TimeUnit.SECONDS);
                    // 更新发送次数

                    if (numberOfSendingWithOneHourInt != 0) {
                        // 没有记录获取过期时间并设置
                        Long overdueTime = redisTemplate.opsForValue().getOperations().getExpire(redisKey);
                        // 没查到过期时间，则重新生成过期时间为一小时
                        if (overdueTime == null) {
                            overdueTime = CommonConst.Time.SECONDS_OF_ONE_HOUR;
                        }
                        redisTemplate.opsForValue().set(redisKey, String.valueOf(numberOfSendingWithOneHourInt + 1), overdueTime, TimeUnit.SECONDS);
                    } else {
                        // 如果没有记录，则新增记录
                        redisTemplate.opsForValue().set(redisKey, "1", CommonConst.Time.SECONDS_OF_ONE_HOUR, TimeUnit.SECONDS);
                    }

                    return Result.getSuccess();
                // 没有短信次数了
                case CommonConst.Phone.NO_MORE_SMS_TIMES:
                    return ErrorCodeEnum.NO_MORE_SMS_TIMES.getResult();
                // 手机号码错误
                case CommonConst.Phone.PHONE_FORMAT_ERROR:
                    return ErrorCodeEnum.PHONE_FORMAT_ERROR.getResult();
                // 短信提交错误
                case CommonConst.Phone.SMS_SEND_SUBMIT_ERROR:
                    return ErrorCodeEnum.SMS_SEND_SUBMIT_ERROR.getResult();
                // 其他错误
                default:
                    return ErrorCodeEnum.SMS_SEND_OTHER_ERRORS.getResult();
            }

        } catch (IOException |
                DocumentException e) {
            log.error(e.toString());
            return ErrorCodeEnum.SMS_SEND_OTHER_ERRORS.getResult();
        }

    }
}
